
/* 
 *
 * Innehåller funktioner för en epost-simulator
 *
 * 
 * 
 * Rev 2008-10-12 Per-Anders Enarsson
 * VERSION: 1.0
 ********************************************************************
 */


#include <stdio.h>                                          // För printf & scanF
#include <stdlib.h>                                         // För malloc
#include <string.h>
#include "esim.h"
#include <time.h>
#include "iniparser.h"
#include "support.h"

/*
 **********************************************************
 * Hämtar in vilket nummer
 **********************************************************
 */

int getNbr(int low, int high)
{
   int i=-1;                                                //Sätt i till ogiltigt
   while(1==1)                                              //Snurra tills break
   {
      printf("\nChoose menu item: \n"); scanf("%i", &i); 
      skipGarb();
      
      if(i>=low&&i<=high)                                   //Förväntar mig low till max, från kallande funktion
         return i;                                          //Returnera resultat
      else{
         printf("\nInvalid input, select from %d to %d \n",low, high); printf("Press enter to continue"); getchar();
      }
   }
}


// ==================================================================
// make configfile
//
// Gör en konfig-fil om det inte finns ngn
// 
void makeConf(){
   char * iniName="esim.ini";
   FILE * fp;
   if ((fp=fopen(iniName, "r"))==NULL) {
      fp=fopen(iniName, "w");
      fprintf(fp,"[conf]\n");
      fprintf(fp,"users=1000\n");
      fprintf(fp,"inmailperday=10\n");
      fprintf(fp,"outmailperday=3\n");
      fprintf(fp,"percentattach=33\n");
      fprintf(fp,"smallatts=20\n");
      fprintf(fp,"medatts=200\n");
      fprintf(fp,"bigatts=2000\n");
      fprintf(fp,"smallattp=60\n");
      fprintf(fp,"bigattp=10\n");
      fprintf(fp,"runtimedays=2\n");
      fclose(fp);
      return;
   }
}

// ==================================================================
// change config
//
// Ändra konfiguration


void changeConfig() {
   int users=1000,inMailPerDay=10,outMailPerDay=3,percentAttach=33;
   int smallAttS=20, medAttS=200, bigAttS=2000;
   int smallAttP=60, bigAttP=10;
   int runTimeDays=10;
   dictionary *dict;                                        //Pekare till didtionaryt som håller config-data
   char * iniName="esim.ini";
   dict = iniparser_load(iniName);                          //ladda data till dictionaryt
   
   while (1==1) {
      users=iniparser_getint(dict, "conf:users", 1000);
      inMailPerDay=iniparser_getint(dict, "conf:inmailperday", 10);
      outMailPerDay=iniparser_getint(dict, "conf:outmailperday", 3);
      percentAttach=iniparser_getint(dict, "conf:percentattach", 33);
      smallAttS=iniparser_getint(dict, "conf:smallatts", 20);
      medAttS=iniparser_getint(dict, "conf:medatts", 200);
      bigAttS=iniparser_getint(dict, "conf:bigatts", 2000);
      smallAttP=iniparser_getint(dict, "conf:smallattp", 60);
      bigAttP=iniparser_getint(dict, "conf:bigattp", 10);
      runTimeDays=iniparser_getint(dict, "conf:runtimedays", 2);
      
      int choise=0,success;
      char inString[10];
      
      clearScreen();
      
      printf("************************************************\n");
      printf("**    Change config                           **\n");
      printf("**    0.quit                                  **\n");
      printf("**    1.Change users           (%6d)       **\n",users); 
      printf("**    2.Change inmail/day      (%6d)       **\n",inMailPerDay); 
      printf("**    3.Change outmail/day     (%6d)       **\n",outMailPerDay); 
      printf("**    4.Change prc with att.   (%6d)       **\n",percentAttach);
      printf("**    5.Change small att. size (%6d)       **\n",smallAttS);
      printf("**    6.Change medium att. size(%6d)       **\n",medAttS);
      printf("**    7.Change big att. size   (%6d)       **\n",bigAttS);
      printf("**    8.Change small att. prc  (%6d)       **\n",smallAttP);
      printf("**    9.Change big att. prc    (%6d)       **\n",bigAttP);
      printf("**   10.Change sim. days       (%6d)       **\n",runTimeDays);
      printf("************************************************\n");
      
      
      choise = getNbr(0,10);                                //Hämta val
      if(choise==0){                                        // om avsluta config är valt, spara ner till fil
         
         FILE * iniFile;
         iniFile = fopen ("esim.ini","w");
         iniparser_dump_ini(dict, iniFile);                 //skriv ner
         fclose(iniFile);
         return;
      }
      
      printf("Ange nummer:");
      scanf("%s",inString);
      skipGarb();
      
      switch(choise)
      {
         case 1:  success=iniparser_set(dict,"conf:users",inString); break;
         case 2:  success=iniparser_set(dict,"conf:inmailperday",inString); break;
         case 3:  success=iniparser_set(dict,"conf:outmailperday",inString); break;
         case 4:  success=iniparser_set(dict,"conf:percentattach",inString); break;
         case 5:  success=iniparser_set(dict,"conf:smallatts",inString); break;
         case 6:  success=iniparser_set(dict,"conf:medatts",inString); break;
         case 7:  success=iniparser_set(dict,"conf:bigatts",inString); break;
         case 8:  success=iniparser_set(dict,"conf:smallattp",inString); break;
         case 9:  success=iniparser_set(dict,"conf:bigattp",inString); break;
         case 10:  success=iniparser_set(dict,"conf:runtimedays",inString); break;
            
         default: break;
      }
   }
   
   
   iniparser_freedict(dict);                                //Frigör dictionaryt
}




// ==================================================================
// Simulera 
// 


void simulate() {
   int users,inMailPerDay=10,outMailPerDay=3,percentAttach=33;
   int smallAttS=20, medAttS=200, bigAttS=2000;
   int smallAttP=60, bigAttP=10;
   int runTimeDays=100,runTimeDaysT, mailTypes=2;
   int *minuteMail, *minuteAtt, *minuteAttSize;
   int runs=0,s0, s1,index=0,attSizePercent;
   
   
   char * iniName="esim.ini";
   dictionary * dict;                                       //Skapa dict
   dict =  iniparser_load(iniName);                         //Och ladda
   users=iniparser_getint(dict, "conf:users", 1);
   inMailPerDay=iniparser_getint(dict, "conf:inmailperday", 1);
   outMailPerDay=iniparser_getint(dict, "conf:outmailperday", 1);
   percentAttach=iniparser_getint(dict, "conf:percentattach", 1);
   smallAttS=iniparser_getint(dict, "conf:smallatts", 1);
   medAttS=iniparser_getint(dict, "conf:medatts", 1);
   bigAttS=iniparser_getint(dict, "conf:bigatts", 1);
   smallAttP=iniparser_getint(dict, "conf:smallattp", 1);
   bigAttP=iniparser_getint(dict, "conf:bigattp", 1);
   runTimeDays=iniparser_getint(dict, "conf:runtimedays", 1);
   
   minuteMail=calloc(1440*runTimeDays,sizeof(int));         //Deklarera minne
   minuteAtt=calloc(1440*runTimeDays,sizeof(int));
   minuteAttSize=calloc(1440*runTimeDays,sizeof(int));
   
   
   srand(time(NULL));
   int runst=users*(outMailPerDay+inMailPerDay)*runTimeDays;//räkna ut antal minuter som skall simuleras
   int runst2=runst/50,stars=0;
   
   while (mailTypes>0) {                                    //Snurra två gånger, räkna först inmail sedan utmail
      runTimeDaysT=runTimeDays;
      while(runTimeDaysT>0){                                //Snurra antal dagar som skall simuleras
         if(mailTypes==2){                                  //Om inkommande mail
            runs=users*inMailPerDay;                        //räkna hur många mail per dag
            s0=(runTimeDaysT-1)*1440;                       //Startminut
            s1=1440;                                        //Slutminut
         }
         else{                                              //om utgående mail
            runs=users*outMailPerDay;                       //Räkna hur många mail per dag
            s0=480+(runTimeDaysT-1)*1440;                   //Startminut
            s1=600;                                         //Slutminut
         }
         
         while(runs>0){                                     //Kör till mail är slut
            
            if (runst--%runst2==0){                         //Progressmeter
               clearScreen();
               printf("||");
               for(int ii=0;ii<stars;ii++)
                  printf("*");
               for(int ii=0;ii<(49-stars);ii++)
                  printf(" ");
               printf("||\n");
               printf("percent done: %d \n",(stars+1)*2);
               stars++;
            }
            
            index=s0+rand()%s1;                             //Slumpa vilken minut mailet hammnat i mellan startminut och slutminut
            minuteMail[index] +=1;                          //Plussa på 1 på minuten
            minuteAttSize[index] +=2;                       //och plussa på 2 på storleken, alla mail har 2 i grundstorlek
            if(rand()%100<percentAttach){                   //Kolla om mailet har attachment
               
               minuteAtt[index] +=1;                        //I så fall addera ett på minuten
               attSizePercent=rand()%100;                   //Och slumpa storlek
               if(attSizePercent<=smallAttP)                //Om litet attatchemnt
                  minuteAttSize[index]+=smallAttS;          //Addera data för litet attachment
               else if(attSizePercent>=100-bigAttP)         //om stort
                  minuteAttSize[index]+= bigAttS;           //addera data
               else                                         //annars är det medium
                  minuteAttSize[index]+= medAttS;           //addera data
            }
            
            
            
            runs--;
         }
         runTimeDaysT--;
      }
      mailTypes--;
   }
   saveData((1440*runTimeDays),minuteMail,minuteAtt, minuteAttSize);//Anropa spara funktion
   free(minuteMail); free(minuteAtt); free(minuteAttSize);  //Återlämna data
   iniparser_freedict(dict);                                //frigör iniparserns minne
   
}

// ==================================================================
// save
// 
// Spara undan data till fil

int saveData(int lines, int *a, int *b, int *c){
   FILE * outDataFile;
   outDataFile = fopen ("esimUnsorted.data","w");
   fprintf(outDataFile, "%8d\n",lines);
   for(int i=0;i<lines;i++){
      fprintf(outDataFile, "%8d%8d%8d%8d\n",i,a[i],b[i],c[i]);
   }
   fclose(outDataFile);
   return 0;
}

// ==================================================================
// read
// 

int result(){
   FILE * inDataFile;
   int *minuteMail, *minuteAtt, *minuteAttSize, i=0,nbr=0, lines,t;
   
   inDataFile = fopen ("esimUnsorted.data","r");
   
   fscanf(inDataFile, "%8d",&lines);                        //Läs första raden i filen för att se hur mycket minne vi behöver
   minuteMail= calloc(lines, sizeof(int));                  //Allokera 
   minuteAtt= calloc(lines, sizeof(int));
   minuteAttSize= calloc(lines, sizeof(int));
   for(i=1;i<lines+1;i++){                                  //Läs in data
      fscanf(inDataFile, "%8d%8d%8d%8d%c",&nbr,&minuteMail[i],&minuteAtt[i],&minuteAttSize[i],&t);
   }
  
   qsort (minuteMail, lines, sizeof(int), compare);         //Sortera
   qsort (minuteAtt, lines, sizeof(int), compare);
   qsort (minuteAttSize, lines, sizeof(int), compare);
   //Skriv ut resultat
   printf("limit:\nMail per minut:            %8d\nVarav mail med attachment: %8d\nAttachment-storlek:        %8d\n",
          minuteMail[lines- lines/200], minuteAtt[lines-lines/200], minuteAttSize[lines-lines/200]);
   printf("Enter to continue");
   getchar();
   free(minuteMail);free(minuteAtt);free(minuteAttSize);    //Återlämna minne
   fclose(inDataFile);
   return 0;
}


// ==================================================================
// compare
// För att qsort skall veta hur data skall sorteras
// 

int compare (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}



